package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.Sign;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.rooms.absrooms.AbsDiffViewChessRoom;
import com.myk.game.gobangchess.rooms.absrooms.movechess.MoreColorCost;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.GridsUtils;
import com.myk.game.gobangchess.utils.Pair;
import com.myk.game.gobangchess.utils.SignsUtils;

import java.util.*;

/**
 * 跳步揭棋
 * sng的中国象棋揭棋变体
 */
public class JumpUncoverChessRoom extends AbsDiffViewChessRoom {

    private CacheSign chessBoardCacheSign; //背景缓存标记
    private final List<int[]> moveArrayList = new ArrayList<>(); // 棋子移动标记
    private List<Chess> chessList; //场上棋子集合
    private Sider blackSider; //游戏黑方实体
    private Sider whiteSider; //游戏白方实体

    public JumpUncoverChessRoom(String roomName) {
        super(roomName, "将跳棋的元素引入中国象棋揭棋的玩法。", "跳步揭棋", GridsUtils.createEmptyGrids(10, 9), true, true);
        initChessBoardCacheSign();
    }

    //棋盘背景的设计
    private void initChessBoardCacheSign() {
        List<Sign> chessboardStyle = new ArrayList<>();
        //背景
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(curGrids.length - 1, curGrids[0].length - 1), MoreColorCost.BOARD_BACKGROUND, MoreColorCost.BOARD_BACKGROUND, 1.8f, 0, 0));
        //边框
        chessboardStyle.add(getPath(0, 0, 0, 8, 2, MoreColorCost.BOARD_LINE));
        chessboardStyle.add(getPath(9, 0, 9, 8, 2, MoreColorCost.BOARD_LINE));
        chessboardStyle.add(getPath(0, 0, 9, 0, 2, MoreColorCost.BOARD_LINE));
        chessboardStyle.add(getPath(0, 8, 9, 8, 2, MoreColorCost.BOARD_LINE));
        //线条
        for (int i = 1; i < 9; i++) {
            chessboardStyle.add(getPath(i, 0, i, 8, 1, MoreColorCost.BOARD_LINE));
        }
        for (int i = 1; i < 8; i++) {
            chessboardStyle.add(getPath(0, i, 4, i, 1, MoreColorCost.BOARD_LINE));
            chessboardStyle.add(getPath(5, i, 9, i, 1, MoreColorCost.BOARD_LINE));
        }
        //九宫青筋代替斜线
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(0, 3), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 0, 1, 0));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(0, 4), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 0, 1, 1));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(0, 5), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 0, 0, 1));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(2, 3), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 1, 0, 0));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(2, 4), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 1, 0, 0));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(2, 5), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 0, 0, 0));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(1, 3), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 1, 1, 0));
        //chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(1, 4), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 1, 1, 1));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(1, 5), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 0, 0, 1));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(8, 3), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 1, 1, 0));
        //chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(8, 4), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 1, 1, 1));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(8, 5), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 0, 0, 1));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(7, 3), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 0, 1, 0));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(7, 4), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 0, 1, 1));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(7, 5), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 0, 0, 1));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(9, 3), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 1, 0, 0));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(9, 4), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 1, 0, 0));
        chessboardStyle.add(FigureSign.makeSingleFigure(getIndex(9, 5), MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 0, 0, 0));
        /*//九宫用黑线加粗
        chessboardStyle.add(getPath(0, 4, 2, 4, 1.2f, MoreColorCost.BOARD_BACKGROUND));
        chessboardStyle.add(getPath(1, 3, 1, 5, 1.2f, MoreColorCost.BOARD_BACKGROUND));

        chessboardStyle.add(getPathDia(0, 4, 2, 4, 1f, MoreColorCost.BOARD_LINE));
        chessboardStyle.add(getPathDia(1, 3, 1, 5, 1f, MoreColorCost.BOARD_LINE));

        chessboardStyle.add(getPath(7, 4, 9, 4, 1.2f, MoreColorCost.BOARD_BACKGROUND));
        chessboardStyle.add(getPath(8, 3, 8, 5, 1.2f, MoreColorCost.BOARD_BACKGROUND));

        chessboardStyle.add(getPathDia(7, 4, 9, 4, 1f, MoreColorCost.BOARD_LINE));
        chessboardStyle.add(getPathDia(8, 3, 8, 5, 1f, MoreColorCost.BOARD_LINE));*/

        //青筋
        List<Integer> veinIndexes = new ArrayList<>();
        veinIndexes.add(getIndex(2, 1));
        veinIndexes.add(getIndex(2, 7));
        veinIndexes.add(getIndex(3, 2));
        veinIndexes.add(getIndex(3, 4));
        veinIndexes.add(getIndex(3, 6));
        veinIndexes.add(getIndex(7, 1));
        veinIndexes.add(getIndex(7, 7));
        veinIndexes.add(getIndex(6, 2));
        veinIndexes.add(getIndex(6, 4));
        veinIndexes.add(getIndex(6, 6));
        chessboardStyle.add(FigureSign.makeBatchSingleFigure(veinIndexes, MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 1, 1, 1));
        List<Integer> vein2Indexes = new ArrayList<>();
        vein2Indexes.add(getIndex(3, 0));
        vein2Indexes.add(getIndex(6, 0));
        chessboardStyle.add(FigureSign.makeBatchSingleFigure(vein2Indexes, MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 1, 1, 0));
        List<Integer> vein3Indexes = new ArrayList<>();
        vein3Indexes.add(getIndex(3, 8));
        vein3Indexes.add(getIndex(6, 8));
        chessboardStyle.add(FigureSign.makeBatchSingleFigure(vein3Indexes, MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 0, 0, 1));

        //楚河汉界
        chessboardStyle.add(new TitleSign(0.25f, 0.5f, 0, "楚  河", MoreColorCost.BOARD_LINE, 0.5f));
        chessboardStyle.add(new TitleSign(0.75f, 0.5f, 0, "汉  界", MoreColorCost.BOARD_LINE, 0.5f));
        //添加到缓存标记
        chessBoardCacheSign = new CacheSign(this, "chessBoardCacheSign", 9, true, chessboardStyle); //*** 修改背景样式记得改这里的版本号！！！
    }

    //棋盘背景路径绘制方法
    public PathSign getPath(final int fRow, final int fCol, final int tRow, final int tCol, final float size, String color) {
        List<Pair<Integer, Integer>> nodes = new ArrayList<>();
        nodes.add(new Pair<>(getIndex(fRow, fCol), 4));
        nodes.add(new Pair<>(getIndex(tRow, tCol), 4));
        return new PathSign(nodes, color, color, size, 0);
    }

    //棋盘背景斜线路径绘制方法
    public PathSign getPathDia(final int fRow, final int fCol, final int tRow, final int tCol, final float size, String color) {
        List<Pair<Integer, Integer>> nodes = new ArrayList<>();
        nodes.add(new Pair<>(getIndex(fRow, fCol), 4));
        nodes.add(new Pair<>(getIndex(tRow, tCol), 4));
        return new PathSign(nodes, color, color, size, 1);
    }

    @Override
    public CacheSign getCacheSignByName(String cacheName) {
        return chessBoardCacheSign;
    }

    @Override
    public String getRuleText() {
        return "《跳步揭棋》\n" +
                "开局双车与将帅为明棋，其他均为暗子。" +
                "暗子按照初始位置对应中象的棋子移动，暗子走动或跳步后均变为明棋，之后按照明棋自身的走法移动。\n" +
                "不论明暗，棋子A只可沿直线或斜线向前跳过相邻本方棋子B到达B的正前方或斜前方相邻空位。\n" +
                "将帅不得出九宫，其他棋子没有限制。";
    }

    @Override
    public String getCoordMode() {
        return "05040000";
    }

    @Override
    public int getCountdownSec() {
        return 180; //传入象棋思考时间比较长，改成300s吧
    }

    @Override
    public String getGameInfo(int viewPoint) {
        //先清空棋盘
        signList.clear();
        //三种身份各自视角的自定义绘制
        if (viewPoint == 1) {
            blackSider.render();
        }
        else if (viewPoint == 2) {
            whiteSider.render();
        }
        else {
            publicRender();
        }
        return super.getGameInfo();
    }

    //公共渲染
    public void publicRender() {
        //画棋盘背景
        signList.add(chessBoardCacheSign);
        //绘制场上棋子
        renderChessList();
        //绘制双方的俘虏预览
        renderCaptiveListPreview();
        //绘制移动箭头
        renderMoveArray();
    }

    //遍历绘制场上棋子
    public void renderChessList() {
        curGrids = GridsUtils.copyGrids(originGrids);
        if (chessList != null) {
            for (Chess piece : chessList) {
                curGrids[piece.row][piece.col] = piece.side; //显示棋子的底座
                if (piece.hideChess == null) { //棋子明棋时才能看到棋子文字
                    signList.add(new TextSign(getIndex(piece.row, piece.col), piece.name, piece.side == 1 ? ColorCost.WHITE : ColorCost.BLACK));
                }
            }
        }
    }

    //绘制双方俘虏预览
    public void renderCaptiveListPreview() {
        if (getCurMode().equals("默认")) {
            if (blackSider != null && whiteSider != null) {
                float leftX = 1 + (0.3f) / curGrids[0].length; //左列位置 棋盘终点再偏移3/10单位格子
                float rightX = 1 + (0.7f) / curGrids[0].length; //右列位置 棋盘终点再偏移7/10单位格子
                float blackTop = (0.5f) / curGrids.length; //黑方预览顶部位置
                float whiteTop = 1 - (0.5f) / curGrids.length; //白方预览顶部位置 （白方是从下往上绘制的）
                float paddingY = 0.0155f / curGrids.length; //因为预览棋子底座和文字大小不同，所以需要做padding，让文字正好显示在底座中心
                float unitH = 0.5f / curGrids.length; //行距定为半个格子
                for (int i = 0; i < blackSider.captiveList.size(); i++) {
                    int j = i / 2; //形成书写文字的排列效果每行两列
                    float bClipY = blackTop + j * unitH;
                    signList.add(new TitleSign(i % 2 == 0 ? leftX : rightX, bClipY, 0, "●", ColorCost.WHITE, 0.35f));
                    signList.add(new TitleSign(i % 2 == 0 ? leftX : rightX, bClipY + paddingY, 0, blackSider.captiveList.get(i).name, ColorCost.BLACK, 0.25f));
                }
                for (int i = 0; i < whiteSider.captiveList.size(); i++) {
                    int j = i / 2;
                    float wClipY = whiteTop - j * unitH;
                    signList.add(new TitleSign(i % 2 == 0 ? leftX : rightX, wClipY, 0, "●", ColorCost.BLACK, 0.35f));
                    signList.add(new TitleSign(i % 2 == 0 ? leftX : rightX, wClipY + paddingY, 0, whiteSider.captiveList.get(i).name, ColorCost.WHITE, 0.25f));
                }
            }
        }
        else {
            if (blackSider != null && whiteSider != null) {
                float leftX = 1 + (0.3f) / curGrids[0].length; //左列位置 棋盘终点再偏移3/10单位格子
                float rightX = 1 + (0.7f) / curGrids[0].length; //右列位置 棋盘终点再偏移7/10单位格子
                float blackTop = (0.5f) / curGrids.length; //黑方预览顶部位置
                float whiteTop = 1 - (0.5f) / curGrids.length; //白方预览顶部位置 （白方是从下往上绘制的）
                float paddingY = 0.0155f / curGrids.length; //因为预览棋子底座和文字大小不同，所以需要做padding，让文字正好显示在底座中心
                float unitH = 0.5f / curGrids.length; //行距定为半个格子
                List<Chess> blackPreviewList = new ArrayList<>(blackSider.captiveList);
                for (int i = 0; i < blackPreviewList.size(); i++) {
                    int j = i / 2; //形成书写文字的排列效果每行两列
                    float bClipY = blackTop + j * unitH;
                    signList.add(new TitleSign(i % 2 == 0 ? leftX : rightX, bClipY, 0, "●", ColorCost.WHITE, 0.35f));
                    signList.add(new TitleSign(i % 2 == 0 ? leftX : rightX, bClipY + paddingY, 0, blackPreviewList.get(i).name, ColorCost.BLACK, 0.25f));
                }
                List<Chess> whitePreviewList = new ArrayList<>(whiteSider.captiveList);
                for (int i = 0; i < whitePreviewList.size(); i++) {
                    int j = i / 2;
                    float wClipY = whiteTop - j * unitH;
                    signList.add(new TitleSign(i % 2 == 0 ? leftX : rightX, wClipY, 0, "●", ColorCost.BLACK, 0.35f));
                    signList.add(new TitleSign(i % 2 == 0 ? leftX : rightX, wClipY + paddingY, 0, whitePreviewList.get(i).name, ColorCost.WHITE, 0.25f));
                }
            }
        }
    }

    //绘制移动箭头
    public void renderMoveArray() {
        for (int[] moveArray : moveArrayList) {
            signList.add(new LineSign(moveArray[0], moveArray[1], ColorCost.MOVE_ARROW_LIGHT, 1));
        }
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        moveArrayList.clear();
        chessList = null;
        blackSider = null;
        whiteSider = null;
    }

    @Override
    protected void onStartPrepare() {
        //初始化场上棋子
        initChessList();
        //初始化对弈双方状态
        blackSider = new Sider(this, 1);
        whiteSider = new Sider(this, 2);
        noticeBlackMove(); //默认通知黑方先行动
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (value == 1) {
            blackSider.doRule(row, col);
        }
        else if (value == 2) {
            whiteSider.doRule(row, col);
        }
    }

    //初始化棋子列表
    private void initChessList() {
        chessList = new ArrayList<>();
        //黑方在上半区
        List<Chess> blackChessList = new ArrayList<>();
        blackChessList.add(new Pawn(this, "兵", 1, 3, 0));
        blackChessList.add(new Pawn(this, "兵", 1, 3, 2));
        blackChessList.add(new Pawn(this, "兵", 1, 3, 4));
        blackChessList.add(new Pawn(this, "兵", 1, 3, 6));
        blackChessList.add(new Pawn(this, "兵", 1, 3, 8));
        blackChessList.add(new Cannon(this, "炮", 1, 2, 1));
        blackChessList.add(new Cannon(this, "炮", 1, 2, 7));
        blackChessList.add(new Horse(this, "馬", 1, 0, 1));
        blackChessList.add(new Horse(this, "馬", 1, 0, 7));
        blackChessList.add(new Bishop(this, "相", 1, 0, 2));
        blackChessList.add(new Bishop(this, "相", 1, 0, 6));
        blackChessList.add(new Guard(this, "仕", 1, 0, 3));
        blackChessList.add(new Guard(this, "仕", 1, 0, 5));
        chessList.addAll(blackChessList);
        chessList.add(new Chariot(this, "車", 1, 0, 0));
        chessList.add(new Chariot(this, "車", 1, 0, 8));
        chessList.add(new General(this, "帅", 1, 0, 4));
        //白方在下半区
        List<Chess> whiteChessList = new ArrayList<>();
        whiteChessList.add(new Pawn(this, "卒", 2, 6, 0));
        whiteChessList.add(new Pawn(this, "卒", 2, 6, 2));
        whiteChessList.add(new Pawn(this, "卒", 2, 6, 4));
        whiteChessList.add(new Pawn(this, "卒", 2, 6, 6));
        whiteChessList.add(new Pawn(this, "卒", 2, 6, 8));
        whiteChessList.add(new Cannon(this, "砲", 2, 7, 1));
        whiteChessList.add(new Cannon(this, "砲", 2, 7, 7));
        whiteChessList.add(new Horse(this, "马", 2, 9, 1));
        whiteChessList.add(new Horse(this, "马", 2, 9, 7));
        whiteChessList.add(new Bishop(this, "象", 2, 9, 2));
        whiteChessList.add(new Bishop(this, "象", 2, 9, 6));
        whiteChessList.add(new Guard(this, "士", 2, 9, 3));
        whiteChessList.add(new Guard(this, "士", 2, 9, 5));
        chessList.addAll(whiteChessList);
        chessList.add(new Chariot(this, "车", 2, 9, 0));
        chessList.add(new Chariot(this, "车", 2, 9, 8));
        chessList.add(new General(this, "将", 2, 9, 4));

        //随机赋值暗子
        List<Chess> blackHideChessList = new ArrayList<>();
        blackHideChessList.add(new Pawn(this, "兵", 1, 3, 0));
        blackHideChessList.add(new Pawn(this, "兵", 1, 3, 2));
        blackHideChessList.add(new Pawn(this, "兵", 1, 3, 4));
        blackHideChessList.add(new Pawn(this, "兵", 1, 3, 6));
        blackHideChessList.add(new Pawn(this, "兵", 1, 3, 8));
        blackHideChessList.add(new Cannon(this, "炮", 1, 2, 1));
        blackHideChessList.add(new Cannon(this, "炮", 1, 2, 7));
        blackHideChessList.add(new Horse(this, "馬", 1, 0, 1));
        blackHideChessList.add(new Horse(this, "馬", 1, 0, 7));
        blackHideChessList.add(new Bishop(this, "相", 1, 0, 2));
        blackHideChessList.add(new Bishop(this, "相", 1, 0, 6));
        blackHideChessList.add(new Guard(this, "仕", 1, 0, 3));
        blackHideChessList.add(new Guard(this, "仕", 1, 0, 5));
        Collections.shuffle(blackHideChessList);
        for (int i = 0; i < blackChessList.size(); i++) {
            blackChessList.get(i).setHideChess(blackHideChessList.get(i)); //赋值暗子
        }
        List<Chess> whiteHideChessList = new ArrayList<>();
        whiteHideChessList.add(new Pawn(this, "卒", 2, 6, 0));
        whiteHideChessList.add(new Pawn(this, "卒", 2, 6, 2));
        whiteHideChessList.add(new Pawn(this, "卒", 2, 6, 4));
        whiteHideChessList.add(new Pawn(this, "卒", 2, 6, 6));
        whiteHideChessList.add(new Pawn(this, "卒", 2, 6, 8));
        whiteHideChessList.add(new Cannon(this, "砲", 2, 7, 1));
        whiteHideChessList.add(new Cannon(this, "砲", 2, 7, 7));
        whiteHideChessList.add(new Horse(this, "马", 2, 9, 1));
        whiteHideChessList.add(new Horse(this, "马", 2, 9, 7));
        whiteHideChessList.add(new Bishop(this, "象", 2, 9, 2));
        whiteHideChessList.add(new Bishop(this, "象", 2, 9, 6));
        whiteHideChessList.add(new Guard(this, "士", 2, 9, 3));
        whiteHideChessList.add(new Guard(this, "士", 2, 9, 5));
        Collections.shuffle(whiteHideChessList);
        for (int i = 0; i < whiteChessList.size(); i++) {
            whiteChessList.get(i).setHideChess(whiteHideChessList.get(i)); //赋值暗子
        }
       /* // 打乱顺序
        List<int[]> blackPositions = new ArrayList<>();
        for (Chess chess : blackChessList) {
            blackPositions.add(new int[]{chess.row, chess.col});
        }
        Collections.shuffle(blackPositions);
        for (int i = 0; i < blackChessList.size(); i++) {
            int[] pos = blackPositions.get(i);
            Chess chess = blackChessList.get(i);
            chess.row = pos[0];
            chess.col = pos[1];
        }

        //打乱顺序
        List<int[]> whitePositions = new ArrayList<>();
        for (Chess chess : whiteChessList) {
            whitePositions.add(new int[]{chess.row, chess.col});
        }
        Collections.shuffle(whitePositions);
        for (int i = 0; i < whiteChessList.size(); i++) {
            int[] pos = whitePositions.get(i);
            Chess chess = whiteChessList.get(i);
            chess.row = pos[0];
            chess.col = pos[1];
        }*/
    }

    //检测胜负
    public void checkOver() {
        stepAdd();
        //胜负判断有点复杂，暂时只判断是否吃掉对方的帅
        if (!hasChessType(chessList, General.class, 2)) {
            doOver(WinMode.BLACK_WIN, "黑方获胜！");
            return;
        }
        else if (!hasChessType(chessList, General.class, 1)) {
            doOver(WinMode.WHITE_WIN, "白方获胜！");
            return;
        }
        //++还要判断是否无棋可走
        //++还要判断是否长将循环
        changeNoticeMove();//切换行动方
    }

    //切换行动方
    public void changeNoticeMove() {
        if (cur == 1) {
            noticeWhiteMove();
        }
        else {
            noticeBlackMove();
        }
    }

    //根据坐标搜索棋子 （有多个棋子时取城门之上的棋子, 可为空）
    public Chess getChessByPos(int row, int col) {
        for (Chess chess : chessList) {
            if (chess.row == row && chess.col == col) {
                return chess;
            }
        }
        return null;
    }

    //根据index搜索棋子 （有多个棋子时取城门之上的棋子, 可为空）
    public Chess getChessByIndex(int index) {
        for (Chess chess : chessList) {
            if (chess.getIndex() == index) {
                return chess;
            }
        }
        return null;
    }

    //检测棋子集合中是否包含某个类型的棋子
    public boolean hasChessType(List<Chess> list, Class<? extends Chess> chessType, int side) {
        for (Chess chess : list) {
            if (chess.getClass() == chessType && chess.side == side) {
                return true;
            }
        }
        return false;
    }

    //检测坐标位置是否在黑方半区
    public int getBoardSideByPos(int row, int col) {
        if (col >= 0 && col < curGrids[0].length) {
            if (row >= 0 && row < curGrids.length / 2) {
                return 1;
            }
            else if (row > curGrids.length / 2 && row < curGrids.length) {
                return 2;
            }
        }
        return 0;
    }

    //检测坐标位置是否在棋盘内
    public boolean isInGrids(int row, int col) {
        return row >= 0 && row < curGrids.length && col >= 0 && col < curGrids[0].length;
    }

    /**
     * 对弈双方的各种信息
     */
    private static class Sider {

        public JumpUncoverChessRoom room;
        private final int side;//归属黑棋还是白棋 1黑  2白
        private final List<Chess> captiveList; //俘虏棋子集合
        private Chess choose; //当前选中的场上棋子

        public Sider(JumpUncoverChessRoom room, int side) {
            this.room = room;
            this.side = side;
            this.captiveList = new ArrayList<>();
        }

        //私有独立界面渲染
        public void render() {
            //画棋盘背景、场上棋子、俘虏预览、移动路径等公共画面
            room.publicRender();
            //场上棋子选中效果等私有画面
            if (choose != null) {
                renderChessChoose();
            }
        }

        //当前选中棋子的绘制
        private void renderChessChoose() {
            //画选中绿框
            room.signList.add(new GroundSign(choose.getIndex(), "#00FFFFFF", "#FF33CC33", 2F, 0, 1));
            //画一下可移动范围
            for (Integer index : choose.getMoveRange()) {
                room.signList.add(new ColorSign(index, MoreColorCost.MOVE));
            }
            //画一下吃子范围
            for (Integer index : choose.getEatRange()) {
                room.signList.add(new ColorSign(index, MoreColorCost.EAT));
            }
        }

        //私有独立交互逻辑处理
        public void doRule(int row, int col) {
            //已选中场上棋子时
            if (choose != null) {
                Chess newChess = room.getChessByPos(row, col);
                //再点击空格
                if (newChess == null) {
                    if (choose.getMoveRange().contains(room.getIndex(row, col))) {
                        moveChess(row, col); //移动选中棋子
                    }
                    else {
                        cancelChoose(); //取消选中棋子
                    }
                }
                //再点击己方棋子时
                else if (newChess.side == side) {
                    chooseChess(newChess); //另选其它己方棋子
                }
                //再点击对方棋子时
                else {
                    if (choose.getEatRange().contains(newChess.getIndex())) {
                        eatChess(newChess); //吃掉对方棋子
                    }
                    else {
                        cancelChoose(); //取消选中棋子
                    }
                }
            }
            //未选中任何棋子时
            else {
                Chess chess = room.getChessByPos(row, col);
                if (chess != null && chess.side == side) {
                    chooseChess(chess);
                }
            }
        }

        //选中棋子
        private void chooseChess(Chess choose) {
            this.choose = choose;
            room.noticeAllRefreshGameInfo();
        }

        //取消场上棋子的选中
        private void cancelChoose() {
            this.choose = null;
            room.noticeAllRefreshGameInfo();
        }

        //移动棋子
        private void moveChess(int row, int col) {
            //更新移动标记
            room.moveArrayList.clear();
            room.moveArrayList.add(new int[]{choose.getIndex(), room.getIndex(row, col)});
            //更新棋子坐标
            choose.row = row;
            choose.col = col;
            //移动过后将暗子转为明子
            showHideChess(choose);
            //移动过后选中状态取消
            choose = null;
            //检查回合是否结束（切换行动方）
            room.checkOver();
        }

        //吃掉棋子
        private void eatChess(Chess target) {
            //更新移动标记
            room.moveArrayList.clear();
            room.moveArrayList.add(new int[]{choose.getIndex(), target.getIndex()});
            //被吃棋子移到拘台
            room.chessList.remove(target);
            captiveList.add(target.hideChess != null ? target.hideChess : target);
            //更新棋子坐标
            choose.row = target.row;
            choose.col = target.col;
            //移动过后将暗子转为明子
            showHideChess(choose);
            //移动过后选中状态取消
            choose = null;
            //检查回合是否结束（切换行动方）
            room.checkOver();
        }

        //将明子转为暗子
        private void showHideChess(Chess choose) {
            if (choose.hideChess != null) {
                choose.hideChess.row = choose.row;
                choose.hideChess.col = choose.col;
                choose.hideChess.side = choose.side;
                choose.hideChess.hideChess = null;
                room.chessList.remove(choose);
                room.chessList.add(choose.hideChess);
                choose.hideChess = null;
            }
        }
    }

    /**
     * 棋子公共抽象类
     */
    private abstract static class Chess {

        public JumpUncoverChessRoom room;
        public String name;
        public int side;
        public int row;
        public int col;
        public Chess hideChess; //暗子代理

        public Chess(JumpUncoverChessRoom room, String name, int side, int row, int col) {
            this.room = room;
            this.name = name;
            this.side = side;
            this.row = row;
            this.col = col;
        }

        //设置暗子代理
        public void setHideChess(Chess chess) {
            this.hideChess = chess;
        }

        //获取棋子的坐标索引
        public int getIndex() {
            return room.getIndex(row, col);
        }

        //获取前方
        protected int getFrontDirection() {
            if (side == 1) {
                return 1;
            }
            else if (side == 2) {
                return -1;
            }
            else {
                return 0;
            }
        }

        //判断自己是否在敌方半区
        protected boolean inEnemyBoard() {
            return isEnemyBoard(row, col);
        }

        //坐标索引是否在敌方半区
        protected boolean isEnemyBoard(int index) {
            if (side == 1) {
                return index >= 45;
            }
            else {
                return index < 45;
            }
        }

        //坐标点是否在敌方半区
        protected boolean isEnemyBoard(int row, int col) {
            if (side == 1) {
                return row >= 5;
            }
            else {
                return row < 5;
            }
        }

        //位置是否是己方九宫格
        protected boolean isSelfPlace(int row, int col) {
            if (side == 1) {
                return row >= 0 && row <= 2 && col >= 3 && col <= 5;
            }
            else {
                return row >= 7 && row <= 9 && col >= 3 && col <= 5;
            }
        }

        //获取自身一周周围的格子（自身为中心“田”区，棋盘范围之外的不加入，最多8个格子）
        protected List<Integer> getAroundRange() {
            int[][] dxdys = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int x = row + dxdy[0];
                int y = col + dxdy[1];
                if (x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && room.curGrids[x][y] == 0) {
                    rangeIndex.add(room.getIndex(x, y));
                }
            }
            return rangeIndex;
        }

        //获取自身前方和斜前方的空格
        protected List<Integer> getFrontAroundRange() {
            int[][] dxdys = {{getFrontDirection(), -1}, {getFrontDirection(), 0}, {getFrontDirection(), 1}};
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int x = row + dxdy[0];
                int y = col + dxdy[1];
                if (x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && room.curGrids[x][y] == 0) {
                    if (room.getChessByPos(x, y) == null) {
                        rangeIndex.add(room.getIndex(x, y));
                    }
                }
            }
            return rangeIndex;
        }

        //获取跳步的范围
        protected List<Integer> getJumpStepRange() {
            List<Integer> rangeIndex = new ArrayList<>();
            Chess leftFrontChess = room.getChessByPos(row + getFrontDirection(), col - 1);
            if (leftFrontChess != null && leftFrontChess.side == this.side && room.isInGrids(row + getFrontDirection() + getFrontDirection(), col - 2) && room.getChessByPos(row + getFrontDirection() + getFrontDirection(), col - 2) == null) {
                rangeIndex.add(room.getIndex(row + getFrontDirection() + getFrontDirection(), col - 2));
            }
            Chess rightFrontChess = room.getChessByPos(row + getFrontDirection(), col + 1);
            if (rightFrontChess != null && rightFrontChess.side == this.side && room.isInGrids(row + getFrontDirection() + getFrontDirection(), col + 2) && room.getChessByPos(row + getFrontDirection() + getFrontDirection(), col + 2) == null) {
                rangeIndex.add(room.getIndex(row + getFrontDirection() + getFrontDirection(), col + 2));
            }
            Chess upFrontChess = room.getChessByPos(row + getFrontDirection(), col);
            if (upFrontChess != null && upFrontChess.side == this.side && room.isInGrids(row + getFrontDirection() + getFrontDirection(), col) && room.getChessByPos(row + getFrontDirection() + getFrontDirection(), col) == null) {
                rangeIndex.add(room.getIndex(row + getFrontDirection() + getFrontDirection(), col));
            }
            return rangeIndex;
        }

        //根据规则搜索棋子默认的移动范围
        protected List<Integer> defMoveRange(int[][] dxdys, int distance) {
            return defMoveRange(dxdys, distance, 0, 0);
        }

        //根据规则搜索棋子默认的移动范围
        protected List<Integer> defMoveRange(int[][] dxdys, int distance, int canJump, int mustJump) {
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int skip = 0;
                for (int x = row + dxdy[0], y = col + dxdy[1], i = 0; x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && i < distance; x += dxdy[0], y += dxdy[1], i++) {
                    Chess chess = room.getChessByPos(x, y);
                    if (chess != null) { //否则遇到棋子阻碍就得停下
                        skip++;
                        if (skip > canJump) {
                            break;
                        }
                        continue;
                    }
                    if (skip >= mustJump) {
                        rangeIndex.add(room.getIndex(x, y));
                    }
                }
            }
            return rangeIndex;
        }

        //根据规则搜索棋子默认的吃子范围
        protected List<Integer> defEatRange(int[][] dxdys, int distance) {
            return defEatRange(dxdys, distance, 0, 0);
        }

        //根据规则搜索棋子默认的吃子范围
        protected List<Integer> defEatRange(int[][] dxdys, int distance, int canJump, int mustJump) {
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int skip = 0;
                for (int x = row + dxdy[0], y = col + dxdy[1], i = 0; x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && i < distance; x += dxdy[0], y += dxdy[1], i++) {
                    Chess chess = room.getChessByPos(x, y);
                    if (chess != null) {
                        if (chess.side != this.side && skip >= mustJump) {
                            rangeIndex.add(room.getIndex(x, y));
                        }
                        skip++;
                        if (skip > canJump) {
                            break;
                        }
                    }
                }
            }
            return rangeIndex;
        }

        /**
         * 自定义 获取可移动空格范围
         */
        public abstract List<Integer> getMoveRange();

        /**
         * 自定义 获取可吃棋子范围
         */
        public abstract List<Integer> getEatRange();

    }

    /**
     * 帅/将
     */
    private static class General extends Chess {
        public General(JumpUncoverChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room, name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            range.addAll(getJumpStepRange());
            range.removeIf(i -> {
                int[] pos = room.getPositionByIndex(i);
                return !isSelfPlace(pos[0], pos[1]);
            });
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = defEatRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            range.removeIf(i -> {
                int[] pos = room.getPositionByIndex(i);
                return !isSelfPlace(pos[0], pos[1]);
            });
            // 白脸杀
            List<Integer> eatRange = defEatRange(new int[][]{{getFrontDirection(), 0}}, Integer.MAX_VALUE);
            for (int index : eatRange) {
                if (room.getChessByIndex(index) instanceof General) {
                    range.add(index);
                }
            }
            return range;
        }

    }

    /**
     * 士
     */
    private static class Guard extends Chess {
        public Guard(JumpUncoverChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room, name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1);
            range.addAll(getJumpStepRange());
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = defEatRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1);
            return range;
        }
    }

    /**
     * 象
     */
    private static class Bishop extends Chess {
        public Bishop(JumpUncoverChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room, name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 2);
            range.removeAll(defMoveRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1));
            range.addAll(getJumpStepRange());
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = defEatRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 2);
            range.removeAll(defEatRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1));
            return range;
        }
    }

    /**
     * 车
     */
    private static class Chariot extends Chess {
        public Chariot(JumpUncoverChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room, name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
            range.addAll(getJumpStepRange());
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            return defEatRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
        }

    }

    /**
     * 马
     */
    private static class Horse extends Chess {
        public Horse(JumpUncoverChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room, name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = new ArrayList<>();
            if (room.getChessByPos(row + 1, col) == null) {
                range.addAll(defMoveRange(new int[][]{{2, 1}, {2, -1}}, 1));
            }
            if (room.getChessByPos(row - 1, col) == null) {
                range.addAll(defMoveRange(new int[][]{{-2, 1}, {-2, -1}}, 1));
            }
            if (room.getChessByPos(row, col + 1) == null) {
                range.addAll(defMoveRange(new int[][]{{1, 2}, {-1, 2}}, 1));
            }
            if (room.getChessByPos(row, col - 1) == null) {
                range.addAll(defMoveRange(new int[][]{{1, -2}, {-1, -2}}, 1));
            }
            range.addAll(getJumpStepRange());
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = new ArrayList<>();
            if (room.getChessByPos(row + 1, col) == null) {
                range.addAll(defEatRange(new int[][]{{2, 1}, {2, -1}}, 1));
            }
            if (room.getChessByPos(row - 1, col) == null) {
                range.addAll(defEatRange(new int[][]{{-2, 1}, {-2, -1}}, 1));
            }
            if (room.getChessByPos(row, col + 1) == null) {
                range.addAll(defEatRange(new int[][]{{1, 2}, {-1, 2}}, 1));
            }
            if (room.getChessByPos(row, col - 1) == null) {
                range.addAll(defEatRange(new int[][]{{1, -2}, {-1, -2}}, 1));
            }
            return range;
        }
    }

    /**
     * 炮
     */
    private static class Cannon extends Chess {
        public Cannon(JumpUncoverChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room, name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
            range.addAll(getJumpStepRange());
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            return defEatRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE, 1, 1);
        }
    }

    /**
     * 兵
     */
    private static class Pawn extends Chess {
        public Pawn(JumpUncoverChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room, name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            if (inEnemyBoard()) {
                List<Integer> range = defMoveRange(new int[][]{{getFrontDirection(), 0}, {0, 1}, {0, -1}}, 1);
                range.addAll(getJumpStepRange());
                return range;
            }
            else {
                List<Integer> range = defMoveRange(new int[][]{{getFrontDirection(), 0}}, 1);
                range.addAll(getJumpStepRange());
                return range;
            }
        }

        @Override
        public List<Integer> getEatRange() {
            if (inEnemyBoard()) {
                return defEatRange(new int[][]{{getFrontDirection(), 0}, {0, 1}, {0, -1}}, 1);
            }
            else {
                return defEatRange(new int[][]{{getFrontDirection(), 0}}, 1);
            }
        }

    }

}
